package com.bjpowernode.money.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSONObject;
import com.bjpowernode.money.constant.UserConstant;
import com.bjpowernode.money.model.FinanceAccount;
import com.bjpowernode.money.model.User;
import com.bjpowernode.money.service.FinanceAccountService;
import com.bjpowernode.money.service.RedisService;
import com.bjpowernode.money.service.UserService;
import com.bjpowernode.money.utils.Result;
import com.bjpowernode.money.utils.YzmCodeUtils;
import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author ZHAOZHENYU
 * @since 2022/10/17
 */

@Controller
public class UserController {

    @Reference(interfaceClass = UserService.class,version = "1.0.0",timeout = 20000)
    private UserService userService;

    @Reference(interfaceClass = RedisService.class,version = "1.0.0",timeout = 20000)
    private RedisService redisService;

    @Reference(interfaceClass = FinanceAccountService.class, version = "1.0.0", timeout = 20000)
    private FinanceAccountService financeAccountService;

    // captcha配置
    @Autowired
    private DefaultKaptcha producer;

    /**
     * 1、跳转注册页面
     * @return
     */
    @GetMapping("/loan/page/register")
    public String register(){
        return "register";
    }

    /**
     * 2、校验手机号是否存在
     * @param phone
     * @return
     */
    @GetMapping("/loan/page/register/checkPhone")
    @ResponseBody
    public Object checkPhone(@RequestParam(name = "phone",required = true) String phone){

        int num = userService.checkPhone(phone);

        if (num != 0){
            return Result.error("用户已存在");
        }else {
            return Result.success();
        }

    }

    /**
     * 3、注册用户 追加短信验证码
     * @param phone
     * @param loginPassword
     * @param messageCode
     * @param request
     * @return
     */
    @PostMapping("/loan/page/register/regUser")
    @ResponseBody
    public Object regUser(@RequestParam(name = "phone",required = true) String phone,
                          @RequestParam(name = "loginPassword",required = true) String loginPassword,
                          @RequestParam(name = "messageCode",required = true) String messageCode,
                          HttpServletRequest request){
        // 后台校验验证码 redis验证
        String yzmCode = redisService.pop(phone);
        if (!StringUtils.equals(messageCode,yzmCode)) {
            return Result.error("验证码错误");
        }
        User user = userService.regUser(phone,loginPassword);
        if (!ObjectUtils.allNotNull(user)){
            return Result.error("注册失败");
        }else {
            // TODO：放入session可用于用户认证
            request.getSession().setAttribute(UserConstant.LOGIN_USER, user);
            // 将id返到前端
            return Result.success();
        }
    }

    /**
     * 4、发送验证码
     * @param phone
     * @return
     */
    @GetMapping("/loan/page/register/sendYzm")
    @ResponseBody
    public Object sendYzm(@RequestParam(name = "phone",required = true) String phone){

        String yzmCode = YzmCodeUtils.generateYzmCode(6);

        Map<String, String> map = new HashMap<>();
        map.put("appkey", "61571f734d70669ee92aa8d1cd683671-bak");
        map.put("mobile", phone);
        map.put("content", "【创信】你的验证码是：" + yzmCode + "，3分钟内有效！");

        String result = null;
        try {
            // httpClient请求第三方平台发送短信验证码 省钱关闭
//            result = HttpClientUtils.doGet("https://way.jd.com/chuangxin/dxjk", map);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("系统异常");
        }

        //模拟报文
        result="{\n" +
                "    \"code\": \"10000\",\n" +
                "    \"charge\": false,\n" +
                "    \"remain\": 0,\n" +
                "    \"msg\": \"查询成功\",\n" +
                "    \"result\": {\n" +
                "        \"ReturnStatus\": \"Success\",\n" +
                "        \"Message\": \"ok\",\n" +
                "        \"RemainPoint\": 1639629,\n" +
                "        \"TaskID\": 85230929,\n" +
                "        \"SuccessCounts\": 1\n" +
                "    },\n" +
                "    \"requestId\": \"825324e71cd64bd7b6bbbda36c74c575\"\n" +
                "}";

        JSONObject jsonObject = JSONObject.parseObject(result);
        String code = jsonObject.getString("code");
        if (!StringUtils.equals("10000",code)){
            return Result.error("通讯异常");
        }
        JSONObject subJsonObject = jsonObject.getJSONObject("result");
        String returnStatus = subJsonObject.getString("ReturnStatus");
        if (!StringUtils.equals("Success",returnStatus)){
            return Result.error("短信发送失败");
        }
        // 放入redis
        redisService.push(phone, yzmCode);

        return Result.success(yzmCode);
    }

    /**
     * 5、跳转到实名认证页面
     * @return
     */
    @GetMapping("/loan/page/register/toRealName")
    public String toRealName(){
        return "realName";
    }

    /**
     * 6、实名认证
     * 检验真实姓名和身份证
     * 校验验证码
     * @param phone
     * @param realName
     * @param idCard
     * @param messageCode
     * @return
     */
    @PostMapping("/loan/page/register/realName")
    @ResponseBody
    public Object realName(@RequestParam(name = "phone",required = true) String phone,
                           @RequestParam(name = "realName",required = true) String realName,
                           @RequestParam(name = "idCard",required = true) String idCard,
                           @RequestParam(name = "messageCode",required = true) String messageCode,
                           HttpServletRequest request){
        // 校验验证码
        String yzmCode = redisService.pop(phone);
        if (!StringUtils.equals(yzmCode, messageCode)) {
            return Result.error("验证码错误");
        }

        // httpClient参数
        Map<String, String> map = new HashMap<>();
        map.put("appkey", "61571f734d70669ee92aa8d1cd683671-bak");
        map.put("cardNo", idCard);
        map.put("realName", realName);

        String result = null;
        try {
            /*result = HttpClientUtils.doGet("https://way.jd.com/youhuoBeijing/test", map);
            System.out.println("result = " + result);*/
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("系统异常");
        }

        // 模拟报文
        result = "{\n" +
                "    \"code\": \"10000\",\n" +
                "    \"charge\": false,\n" +
                "    \"remain\": 1305,\n" +
                "    \"msg\": \"查询成功\",\n" +
                "    \"result\": {\n" +
                "        \"error_code\": 0,\n" +
                "        \"reason\": \"成功\",\n" +
                "        \"result\": {\n" +
                "            \"realname\": \"乐天磊\",\n" +
                "            \"idcard\": \"350721197702134399\",\n" +
                "            \"isok\": true\n" +
                "        }\n" +
                "    }\n" +
                "}";

        JSONObject jsonObject = JSONObject.parseObject(result);
        String code = jsonObject.getString("code");
        if (!StringUtils.equals("10000",code)){
            return Result.error("通讯异常");
        }

        JSONObject subJsonObject = jsonObject.getJSONObject("result");
        JSONObject subSubJSONObject = subJsonObject.getJSONObject("result");
        String isok = subSubJSONObject.getString("isok");
        if (!StringUtils.equals("true",isok)){
            return Result.error("身份验证失败");
        }

        User user = new User();
        user.setIdCard(idCard);
        user.setName(realName);
        // TODO: userId从session取出
        User user_session = (User) request.getSession().getAttribute(UserConstant.LOGIN_USER);
        user.setId(user_session.getId());

        // 更新用户信息
        int num = userService.updateById(user);
        if(num == 0) return Result.error("更新数据失败");

        // 认证完成后更新session
        user_session.setIdCard(idCard);
        user_session.setName(realName);
        request.getSession().setAttribute(UserConstant.LOGIN_USER, user_session);

        return Result.success();

    }

    /**
     * 7、根据userId验证手机号是否一致
     * @param phone
     * @param request
     * @return
     */
    @GetMapping("/loan/page/register/checkOnePhone")
    @ResponseBody
    public Object checkPhoneById(@RequestParam(name = "phone",required = true) String phone,
                                 HttpServletRequest request){

        // TODO：取出session的userId
        User user_session = (User) request.getSession().getAttribute(UserConstant.LOGIN_USER);
        boolean flag = userService.checkPhoneById(phone,user_session.getId());

        if (!flag){
            return Result.error("手机号不一致");
        }else {
            return Result.success();
        }

    }

    /**
     * 8、跳转登录页面
     * @return
     */
    @GetMapping("/loan/page/login")
    public String toLogin(){
        return "login";
    }

    /**
     * 9、用户 登录：验证账号密码
     * (1)账号密码查数据库  无法确定账号错误还是密码错误 √
     * (2)账号查出用户信息再对比   不安全
     */
    @PostMapping("/loan/page/doLogin")
    @ResponseBody
    public Object doLogin(@RequestParam(name = "phone",required = true) String phone,
                          @RequestParam(name = "loginPassword",required = true) String loginPassword,
                          HttpServletRequest request){
        User user = userService.loginUser(phone,loginPassword);
        if (!ObjectUtils.allNotNull(user)){
            return Result.error("账号或密码错误");
        }
        request.getSession().setAttribute(UserConstant.LOGIN_USER, user);
        return Result.success();
    }

    /**
     * 10、用户下拉框显示账户余额
     * @return
     */
    @GetMapping("/loan/page/FinanceAccount")
    @ResponseBody
    public Object queryFinance(HttpServletRequest request){
        User user_session = (User) request.getSession().getAttribute(UserConstant.LOGIN_USER);
        if (!ObjectUtils.allNotNull(user_session)) {
            return Result.error("请先登录");
        }
        FinanceAccount financeAccount = financeAccountService.queryFinanceByUserId(user_session.getId());
        if (!ObjectUtils.allNotNull(financeAccount)) {
            return Result.error("financeAccount为空");
        }
        return Result.success(financeAccount.getAvailableMoney() + "");
    }

    /**
     * 11、登录：kaptcha图片验证码
     * @param request
     * @param response
     * @return
     */
    @GetMapping("/loan/page/captcha")
    public void captcha(HttpServletRequest request, HttpServletResponse response){

        HttpSession session = request.getSession();
        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        response.setContentType("image/jpeg");
        //生成验证码
        String capText = producer.createText();
//        System.out.println("capText = " + capText);
        //向客户端写出
        session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
        BufferedImage bi = producer.createImage(capText);
        // 放入session 便于比较
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
            ImageIO.write(bi, "jpg", out);
            out.flush();
        }catch (Exception e){
            e.printStackTrace();
        } finally{
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 12、登录：异步返回session里面的图片验证码数据给前段，同步会延迟
     * @param request
     * @return
     */
    @GetMapping("/loan/page/checkCaptcha")
    @ResponseBody
    public String checkCaptcha(HttpServletRequest request){
        return (String) request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
    }

    /**
     * 13、退出登录
     * @param request
     * @return
     */
    @GetMapping("/loan/logout")
    public String logout(HttpServletRequest request){
        // 销毁session退出登录
        request.getSession().invalidate();
        // 重定向主页面
        return "redirect:/index";
    }

}
